home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / fmsdisk / fms < prev    next >
Text File  |  1993-10-10  |  10KB  |  434 lines

  1. /*
  2.  *  FMS.C
  3.  *
  4.  *  File Disk Device (fmsdisk.device)
  5.  *
  6.  *  Simulates a trackdisk by using a large file to hold the 'blocks'.
  7.  *  Mod - CAS - 7/93: look for ENV:FMSUnit<n> containing path to file,
  8.  *        then fall back to old FMS:Unit<n> as filename if ENV not found
  9.  */
  10.  
  11. #include <exec/types.h>
  12. #include <exec/nodes.h>
  13. #include <exec/errors.h>
  14. #include <exec/memory.h>
  15. #include <devices/trackdisk.h>
  16. #include <dos/dos.h>
  17. #include <dos/dosextens.h>
  18. #include <stdio.h>
  19.  
  20. #include <clib/exec_protos.h>
  21. #include <clib/dos_protos.h>
  22. #include <clib/alib_protos.h>
  23.  
  24. extern struct Library *SysBase;
  25. extern struct DosLibrary *DosBase;
  26. #include <pragmas/exec_pragmas.h>
  27. #include <pragmas/dos_pragmas.h>
  28.  
  29.  
  30. /*#define DEBUG*/
  31.  
  32. #define CMD_OPENUNIT    (0x7FF0 & ~TDF_EXTCOM)
  33. #define CMD_CLOSEUNIT    (0x7FF1 & ~TDF_EXTCOM)
  34. #define CMD_KILLPROC    (0x7FF2 & ~TDF_EXTCOM)
  35.  
  36. typedef struct Library    LIB;
  37. typedef struct Device    DEV;
  38. typedef struct Process    PROC;
  39. typedef struct MsgPort    PORT;
  40. typedef struct Message    MSG;
  41. typedef struct List    LIST;
  42. typedef struct Node    NODE;
  43. typedef long (*func_ptr)();
  44.  
  45. typedef struct {
  46.     struct  Unit    U;
  47.     UWORD   OpenCnt;
  48.     long    Fh;     /*  file handle     */
  49.     long    Size;    /*  current size    */
  50.     char    NotSyn;
  51.     char    Reserved;
  52. } NDUnit;
  53.  
  54. typedef struct {
  55.     LIB     Lib;
  56.     NDUnit  Unit[32];
  57. } NDev;
  58.  
  59. typedef struct {
  60.     struct  Message io_Message;
  61.     struct  Device  *io_Device;     /* device node pointer  */
  62.     struct  Unit    *io_Unit;        /* unit (driver private)*/
  63.     UWORD   io_Command;         /* device command */
  64.     UBYTE   io_Flags;
  65.     BYTE    io_Error;            /* error or warning num */
  66.     ULONG   io_Actual;            /* actual number of bytes transferred */
  67.     ULONG   io_Length;            /* requested number bytes transferred*/
  68.     APTR    io_Data;            /* points to data area */
  69.     ULONG   io_Offset;            /* offset for block structured devices */
  70.  
  71.     long    iotd_Count;         /*    (extension)     */
  72.     long    iotd_SecLabel;        /*    (extension)     */
  73. } IOB;
  74.  
  75.  
  76. void SynchroMsg(UWORD cmd, struct Unit *unit);
  77. void ExtendSize(NDUnit *unit, long offset);
  78. void GetUnitName(int unitnum, char *buf);
  79.  
  80. extern char DeviceName[];
  81. extern char IdString[];
  82. extern void DUMmySeg();
  83.  
  84. typedef NDev    *NDevP;
  85. typedef IOB    *IOBP;
  86.  
  87. struct Library *SysBase    = NULL;
  88. struct DosLibrary *DOSBase    = NULL;
  89.  
  90. NDev *DevBase    = NULL;
  91. APTR DevSegment = NULL;
  92. PORT *FProc    = NULL;
  93. PORT FPort;
  94.  
  95. extern func_ptr DevVectors[];
  96.  
  97. __saveds NDevP    __asm
  98. Init(register __a0 APTR seg)
  99. {
  100.     NDev *db;
  101.  
  102.     SysBase = (struct Library *)(*(ULONG *)4);
  103.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
  104.  
  105.     DevBase = db = (NDev *)MakeLibrary((long **)DevVectors,NULL,NULL,sizeof(NDev),NULL);
  106.     db->Lib.lib_Node.ln_Type = NT_DEVICE;
  107.     db->Lib.lib_Node.ln_Name = DeviceName;
  108.     db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  109.     db->Lib.lib_Version = 1;
  110.     db->Lib.lib_IdString= (APTR)IdString;
  111.  
  112.     DevSegment = seg;
  113.     AddDevice((DEV *)db);
  114.     return(db);
  115. }
  116.  
  117. __saveds NDevP __asm
  118. DevOpen(register __d0 long unitnum,
  119.     register __a1 IOBP iob,
  120.     register __d1 long flags
  121.        )
  122. {
  123.     NDev *nd = DevBase;
  124.     NDUnit *unit = &nd->Unit[unitnum];
  125.  
  126.     if (++nd->Lib.lib_OpenCnt == 1) {
  127.     FProc = CreateProc("FMS-Dummy", 0, (long)DUMmySeg >> 2, 4096);
  128.     FPort.mp_SigBit = SIGBREAKB_CTRL_D;    /*  port init */
  129.     FPort.mp_SigTask= FProc->mp_SigTask;
  130.     FPort.mp_Flags = PA_SIGNAL;
  131.     NewList(&FPort.mp_MsgList);
  132.     }
  133.  
  134.     if (++unit->OpenCnt == 1)
  135.     SynchroMsg(CMD_OPENUNIT, unit);
  136.  
  137.     nd->Lib.lib_Flags &= ~LIBF_DELEXP;
  138.     iob->io_Unit = (struct Unit *)unit;
  139.     iob->io_Error = 0;
  140.     return(nd);
  141. }
  142.  
  143.  
  144. __saveds APTR
  145. DevExpunge(void)
  146. {
  147.     NDev *nd = DevBase;
  148.  
  149.     if (DevSegment == NULL)
  150.     Alert(24);
  151.     if (nd->Lib.lib_OpenCnt) {
  152.     nd->Lib.lib_Flags |= LIBF_DELEXP;
  153.     return(NULL);
  154.     }
  155.     Remove((NODE *)nd);
  156.     FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
  157.     DevSegment = NULL;
  158.     return(DevSegment);
  159. }
  160.  
  161. __saveds APTR __asm
  162. DevClose(register __a1 IOBP iob)
  163. {
  164.     NDev *nd = DevBase;
  165.  
  166.     {
  167.     NDUnit *unit = (NDUnit *)iob->io_Unit;
  168.     if (unit->OpenCnt && --unit->OpenCnt == 0)
  169.         SynchroMsg(CMD_CLOSEUNIT, unit);
  170.     }
  171.  
  172.     if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
  173.     return(NULL);
  174.     if (FProc) {
  175.     SynchroMsg(CMD_KILLPROC, NULL);
  176.     FProc = NULL;
  177.     }
  178.     if (nd->Lib.lib_Flags & LIBF_DELEXP)
  179.     return(DevExpunge());
  180.     /*
  181.      *    close down resources
  182.      */
  183.     return(NULL);
  184. }
  185.  
  186. __saveds void __asm
  187. DevBeginIO(register __a1 IOBP iob)
  188. {
  189.     /*NDev *nd = DevBase;*/
  190.  
  191.     iob->io_Error = 0;
  192.     iob->io_Actual = 0;
  193.  
  194.     switch(iob->io_Command & ~TDF_EXTCOM) {
  195.     case CMD_INVALID:
  196.     iob->io_Error = IOERR_NOCMD;
  197.     break;
  198.     case CMD_RESET:
  199.     break;
  200.     case CMD_READ:
  201.     PutMsg(&FPort, &iob->io_Message);
  202.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  203.     iob = NULL;
  204.     break;
  205.     case CMD_WRITE:
  206.     PutMsg(&FPort, &iob->io_Message);
  207.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  208.     iob = NULL;
  209.     break;
  210.     case CMD_UPDATE:
  211.     break;
  212.     case CMD_CLEAR:
  213.     break;
  214.     case CMD_STOP:
  215.     break;
  216.     case CMD_START:
  217.     break;
  218.     case CMD_FLUSH:
  219.     break;
  220.     case TD_MOTOR:        /*    motor,    no action   */
  221.     case TD_SEEK:        /*    seek,    no action   */
  222.     break;
  223.     case TD_FORMAT:        /*    format            */
  224.     PutMsg(&FPort, &iob->io_Message);
  225.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  226.     iob = NULL;
  227.     break;
  228.     case TD_REMOVE:        /*    not supported        */
  229.     iob->io_Error = IOERR_NOCMD;
  230.     break;
  231.     case TD_CHANGENUM:        /*    change count never changes  */
  232.     iob->io_Actual = 1;
  233.     break;
  234.     case TD_CHANGESTATE:    /*    0=disk in drive     */
  235.     iob->io_Actual = 0;
  236.     break;
  237.     case TD_PROTSTATUS:     /*    io_Actual -> 0 (rw) */
  238.     iob->io_Actual = 0;
  239.     break;
  240.     case TD_RAWREAD:        /*    not supported        */
  241.     case TD_RAWWRITE:
  242.     iob->io_Error = IOERR_NOCMD;
  243.     break;
  244.     case TD_GETDRIVETYPE:   /*    drive type?        */
  245.     iob->io_Actual = 0;
  246.     break;
  247.     case TD_GETNUMTRACKS:
  248.     iob->io_Actual = 0; /*    # of tracks?        */
  249.     break;
  250.     case TD_ADDCHANGEINT:   /*    action never taken  */
  251.     case TD_REMCHANGEINT:
  252.     break;
  253.     default:
  254.     iob->io_Error = IOERR_NOCMD;
  255.     break;
  256.     }
  257.     if (iob) {
  258.     if ((iob->io_Flags & IOF_QUICK) == 0)
  259.         ReplyMsg((MSG *)iob);
  260.     }
  261. }
  262.  
  263. __saveds void __asm
  264. DevAbortIO(register __a1 IOBP iob)
  265. {
  266.     /*NDev *nd = DevBase;*/
  267. }
  268.  
  269. func_ptr DevVectors[] = {
  270.     (func_ptr)DevOpen,
  271.     (func_ptr)DevClose,
  272.     (func_ptr)DevExpunge,
  273.     NULL,
  274.     (func_ptr)DevBeginIO,
  275.     (func_ptr)DevAbortIO,
  276.     (func_ptr)-1
  277. };
  278.  
  279. /*
  280.  *  Server communications
  281.  */
  282.  
  283. void
  284. SynchroMsg(UWORD cmd, struct Unit *unit)
  285. {
  286.     IOB Iob;
  287.  
  288.     Iob.io_Message.mn_ReplyPort = CreatePort(NULL, 0);
  289.     Iob.io_Command = cmd;
  290.     Iob.io_Unit = unit;
  291.  
  292.     PutMsg(&FPort, &Iob.io_Message);
  293.     WaitPort(Iob.io_Message.mn_ReplyPort);
  294.     DeletePort(Iob.io_Message.mn_ReplyPort);
  295. }
  296.  
  297. /*
  298.  *    SERVER SIDE (IS A PROCESS)
  299.  *
  300.  *    File name is:
  301.  */
  302.  
  303. __saveds void
  304. CoProc(void)
  305. {
  306.     IOBP iob;
  307.     NDUnit *unit;
  308.     char buf[128];
  309.     char notdone = 1;
  310. #ifdef DEBUG
  311.     long fh = Open("con:0/0/320/100/Debug", 1006);
  312. #endif
  313.  
  314.     Wait(SIGBREAKF_CTRL_D);     /*  wait for port init  */
  315.  
  316.     while (notdone) {
  317.     WaitPort(&FPort);
  318.     while (iob = (IOBP)GetMsg(&FPort)) {
  319.         unit = (NDUnit *)iob->io_Unit;
  320.  
  321. #ifdef DEBUG
  322.         sprintf(buf, "Cmd %08lx/%04x @ %08lx Buf %08lx %04x\n",
  323.         unit, iob->io_Command, iob->io_Offset, iob->io_Data, iob->io_Length
  324.         );
  325.         Write(fh, buf, strlen(buf));
  326. #endif
  327.         switch(iob->io_Command & ~TDF_EXTCOM) {
  328.         case CMD_OPENUNIT:
  329.         GetUnitName(unit - &DevBase->Unit[0], buf);
  330.         unit->Fh = Open(buf, 1005);
  331.         if (unit->Fh == NULL) {
  332.             unit->Fh = Open(buf, 1006);
  333.             unit->NotSyn = 1;
  334.         }
  335.         if (unit->Fh) {
  336.             Seek(unit->Fh, 0L, 1);
  337.             unit->Size = Seek(unit->Fh, 0L, -1);
  338.         }
  339.         break;
  340.         case CMD_CLOSEUNIT:
  341.         if (unit->Fh) {
  342.             Close(unit->Fh);
  343.             unit->Fh = NULL;
  344.         }
  345.         break;
  346.         case CMD_KILLPROC:
  347.         notdone = 0;
  348.         break;
  349.         case CMD_READ:
  350.         if (unit->Fh == NULL)
  351.             break;
  352.         if (iob->io_Offset + iob->io_Length > unit->Size)
  353.             ExtendSize(unit, iob->io_Offset + iob->io_Length);
  354.         Seek(unit->Fh, iob->io_Offset, -1);
  355.         iob->io_Actual = Read(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  356.         break;
  357.         case CMD_WRITE:
  358.         /*
  359.          *  This causes file to be closed/reopened after
  360.          *  formatting.
  361.          */
  362.         if (unit->NotSyn && unit->Fh) {
  363.             Close(unit->Fh);
  364.             GetUnitName(unit - &DevBase->Unit[0], buf);
  365.             unit->Fh = Open(buf, 1005);
  366.             unit->NotSyn = 0;
  367.         }
  368.         /* fall through */
  369.         case TD_FORMAT:
  370.         if (unit->Fh == NULL)
  371.             break;
  372.  
  373.         if (iob->io_Offset > unit->Size)
  374.             ExtendSize(unit, iob->io_Offset);
  375.         Seek(unit->Fh, iob->io_Offset, -1);
  376.         iob->io_Actual = Write(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  377.         break;
  378.         }
  379.  
  380.         if (notdone == 0)       /*  forbid before falling through */
  381.         Forbid();           /*  and esp before replying       */
  382.         ReplyMsg(&iob->io_Message);
  383.     }
  384.     }
  385.     /* fall through to exit */
  386. }
  387.  
  388. void
  389. GetUnitName(int unitnum, char *buf)
  390. {
  391. BPTR envfile;
  392. LONG envlen;
  393. BOOL gotit = FALSE;
  394.  
  395. /* New - see if ENVIRONMENT variable FMSUnit<n> exists (ex. FMSUnit2)
  396.  * containing full path to file.
  397.  */
  398. sprintf(buf,"ENV:FMSUnit%d",unitnum);
  399. if(envfile = Open(buf,MODE_OLDFILE))
  400.     {
  401.     envlen = Read(envfile,buf,128-2);
  402.     if(envlen >= 0)
  403.     {
  404.     gotit = TRUE;
  405.     buf[envlen] = '\0';
  406.         if(buf[envlen-1]=='\n') buf[envlen-1] = '\n';
  407.     }
  408.     Close(envfile);
  409.     }
  410. /* Fallback to old FMS:Unit<n> name */
  411. if(!gotit)
  412.     {
  413.     sprintf(buf, "FMS:Unit%d", unitnum);
  414.     }
  415. }
  416.  
  417. void
  418. ExtendSize(NDUnit *unit, long offset)
  419. {
  420.     long pos;
  421.     char *buf = AllocMem(512, MEMF_CLEAR|MEMF_PUBLIC);
  422.  
  423.     if (unit->NotSyn == 0)
  424.     unit->NotSyn = 1;
  425.     Seek(unit->Fh, 0L, 1);
  426.     pos = Seek(unit->Fh, 0L, 0);
  427.     while (pos < offset) {
  428.     if (Write(unit->Fh, buf, 512) != 512)
  429.         break;
  430.     pos += 512;
  431.     }
  432.     FreeMem(buf, 512);
  433. }
  434.